package com.acs.player.media;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.content.Context;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;

import com.acs.player.PlayerActivity;
import com.acs.player.entities.Album;
import com.acs.player.entities.Music;

public class Player implements OnCompletionListener {
	
	private static WakeLock wakeLock;
	private static boolean isTuning;
	private static Random random;
	private static boolean shuffle; 
	private static int indexCurrentTrack = -1;
	private static String currentTrack;

	private static List<Music> trackListsToPlay = new ArrayList<Music>();
	private static PlayerActivity playerActivity;
	private String currentActivity;

	private static MediaPlayer mediaPlayer;
	private boolean isPrepared = false;
	
	private static Player instance;
	
	private Player(){
		
	};

	public static Player getPlayer(){
		if(instance == null){
			instance = new Player();
		}					
		return instance;
	}
	
	public void setDescriptor(String trackPath){
		
		try{
	    	File file = new File(trackPath);
			FileInputStream fis = new FileInputStream(file);
			FileDescriptor fileDescriptor = fis.getFD();

			if(mediaPlayer != null){
				mediaPlayer.stop();		
			}
			
			mediaPlayer = new MediaPlayer();
			mediaPlayer.setDataSource(fileDescriptor);
			mediaPlayer.prepare();
			mediaPlayer.setOnCompletionListener(this);
			mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
			
			@Override
			public void onCompletion(MediaPlayer player) {
				if(isLooping()){
					playTrack();
				} else {
					if (isShuffle()){
						setShuffle();
					} else {
						setTrack(1);	
					}		
					
					loadTrack();
					playTrack();

					Music music = trackListsToPlay.get(indexCurrentTrack);		
					playerActivity.updateCover(music.getAlbulm().getImagePath());
				}
			}
		});
			
			isPrepared = true;
		} catch(Exception ex){
			throw new RuntimeException("Couldn't load music, uh oh!");
		}
	}
    
    public String getCurrentCover(){
    	Music track = trackListsToPlay.get(indexCurrentTrack);
    	Album album = track.getAlbulm();
    	String coverPath = album.getImagePath();
    	
    	return coverPath;
    }
    
	public void onPause(){
		wakeLock.release();
		if(instance != null){
			if(isPlaying()){
				pause();
				isTuning = false;
			}
		} 
	}
    
    public void onResume(){
    	wakeLock.acquire();
    }
    
    public void initialize(PlayerActivity activity){	
    	playerActivity = activity;
		PowerManager powerManager = (PowerManager) playerActivity.getSystemService(Context.POWER_SERVICE);
		wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "Lexiconda");
		
    	shuffle = false;
    	isTuning = false;
    	random = new Random();
    }
    
    public void pauseSelection(){
		isTuning = false;
		pause();
    }
	
    public void playSelection(){
		isTuning = true;
		playTrack();	
    }
    
    public void setShuffle() {
		int temp = random.nextInt(trackListsToPlay.size());
		while(true){
			if(temp != indexCurrentTrack){
				indexCurrentTrack = temp;
				break;
			}
			temp++;
			if(temp > trackListsToPlay.size()-1){
				temp = 0;
			}
		}
	}
    

	/**
     * Loads the track by calling loadMusic
     */
    public void loadTrack(){
    	if(trackListsToPlay.size() > 0){
        	Music music = trackListsToPlay.get(indexCurrentTrack);
        	currentTrack = music.getPath();
        	String trackPath = music.getPath(); 

    		setDescriptor(trackPath);
    	}
    }
    
    public void setTrack(int direction){
    	if(direction == 0){
    		indexCurrentTrack--;
			if(indexCurrentTrack < 0){
				indexCurrentTrack = trackListsToPlay.size()-1;
			}
    	} else if(direction == 1){
    		indexCurrentTrack++;
			if(indexCurrentTrack > trackListsToPlay.size()-1){
				indexCurrentTrack = 0;
			}
    	}
    	if(shuffle){
			int temp = random.nextInt(trackListsToPlay.size());
			while(true){
				if(temp != indexCurrentTrack){
					indexCurrentTrack = temp;
					break;
				}
				temp++;
				if(temp > trackListsToPlay.size()-1){
					temp = 0;
				}
			}
		} 
    }
	
	
	// FONCTIONS BASE
    
	public void onCompletion(MediaPlayer mediaPlayer) {
		synchronized(this){
			isPrepared = false;
		}
	}

	public void playTrack() {
		if(mediaPlayer.isPlaying()){
			return;
		}
		try{
			synchronized(this){
				if(!isPrepared){
					mediaPlayer.prepare();
				}
				mediaPlayer.start();
			}
		} catch(IllegalStateException ex){
			ex.printStackTrace();
		} catch(IOException ex){
			ex.printStackTrace();
		}
	}

	public void stop() {
		mediaPlayer.stop();
		synchronized(this){
			isPrepared = false;
		}
	}
	
	public void switchTracks(){
		mediaPlayer.seekTo(0);
		mediaPlayer.pause();
	}
	
	public void pause() {
		mediaPlayer.pause();
	}

	public static boolean isPlaying() {
		return mediaPlayer.isPlaying();
	}
	
	public boolean isLooping() {
		return mediaPlayer.isLooping();
	}
	
	public void setLooping(boolean isLooping) {
		mediaPlayer.setLooping(isLooping);
	}

	public void setVolume(float volumeLeft, float volumeRight) {
		mediaPlayer.setVolume(volumeLeft, volumeRight);
	}

	public void dispose() {
		if(mediaPlayer.isPlaying()){
			stop();
		}
		mediaPlayer.release();
	}

	public boolean isShuffle() {
		return shuffle;
	}

	public void setShuffle(boolean shuffle) {
		this.shuffle = shuffle;
	}

	public List<Music> getTrackListsToPlay() {
		return trackListsToPlay;
	}

	public void setTrackListsToPlay(List<Music> trackLists) {
		trackListsToPlay = trackLists;
	}

	public int getIndexCurrentTrack() {
		return indexCurrentTrack;
	}

	public void setIndexCurrentTrack(int currentTrack) {
		this.indexCurrentTrack = currentTrack;
	}

	public boolean isTuning() {
		return isTuning;
	}

	public void setTuning(boolean isTuning) {
		this.isTuning = isTuning;
	}

	public int getDuration() {
		return mediaPlayer.getDuration();
	}
	
	public int getCurrentPosition() {
		return mediaPlayer.getCurrentPosition();
		
	}
	
	public void seekTo(int msec){
		mediaPlayer.seekTo(msec);
	}

	public String getCurrentActivity() {
		return currentActivity;
	}

	public void setCurrentActivity(String currentActivity) {
		this.currentActivity = currentActivity;
	}

	public static String getCurrentTrack() {
		return currentTrack;
	}

}
